<?php

/**
 * @Author: Wang Chunsheng 2192138785@qq.com
 * @Date:   2020-03-04 01:13:34
 * @Last Modified by:   Wang Chunsheng 2192138785@qq.com
 * @Last Modified time: 2020-03-14 20:42:37
 */


namespace api\modules\diandi_shop;

use Yii;
use app\modules\diandi_shop\models\DdGoods;
use app\modules\diandi_shop\models\DdOrder;
use app\modules\diandi_shop\models\DdOrderGoods;
use app\modules\diandi_shop\models\enums\OrderStatus;
use common\helpers\FileHelper;
use common\models\DdCorePaylog;
use yii\helpers\Json;
use common\helpers\ArrayHelper;

use function GuzzleHttp\json_decode;;

/**
 * DiandiShop module definition class
 */
class module extends \yii\base\Module
{
    /**
     * {@inheritdoc}
     */
    public $controllerNamespace = 'api\modules\diandi_shop\controllers';

    /**
     * {@inheritdoc}
     */
    public function init()
    {
        parent::init();
        $config = require(__DIR__ . '/config.php');
        // 获取应用程序的组件
        $components = \Yii::$app->getComponents();
        // 加载后台模块中的models

        \Yii::setAlias('@app/modules/diandi_shop/models', '@backend/modules/diandi_shop/models');

        // 遍历子模块独立配置的组件部分，并继承应用程序的组件配置
        foreach ($config['components'] as $k => $component) {
            if (isset($component['class']) && isset($components[$k]) == false) {
                continue;
            }
            $config['components'][$k] = array_merge($components[$k], $component);
        }
        // 将新的配置设置到应用程序
        // 很多都是写 Yii::configure($this, $config)，但是并不适用子模块，必须写 Yii::$app
        \Yii::configure(\Yii::$app, $config);
        // custom initialization code goes here
    }

    // 支付回调
    // {
    //     "appid": "wx028eb56f4b4a7d99",
    //     "bank_type": "OTHERS",
    //     "cash_fee": "5",
    //     "fee_type": "CNY",
    //     "is_subscribe": "N",
    //     "mch_id": "1228641802",
    //     "nonce_str": "5e6be567474bb",
    //     "openid": "oE5EC0aqNTAdAXpPfikBpkHiSG1o",
    //     "out_trade_no": "2020031455505497",
    //     "result_code": "SUCCESS",
    //     "return_code": "SUCCESS",
    //     "sign": "99C78A7B9A9110E9A4EA4D5040596700",
    //     "time_end": "20200314035649",
    //     "total_fee": "5",
    //     "trade_type": "JSAPI",
    //     "transaction_id": "4200000518202003141950666245"
    // }
    /**
     * Undocumented function
     *
     * @param [type] $params
     * @return void
     */
    public function Notify($params)
    {
        $logPath =  __DIR__ . '/../wechat/log/paynotify/wechat.log';
        FileHelper::writeLog($logPath, '模块内回调' . $params['out_trade_no']);
        //支付金额校验
        $orderInfo = DdOrder::findOne(['order_no' => $params['out_trade_no']]);
        FileHelper::writeLog($logPath, '订单获取' . Json::encode($orderInfo));

        FileHelper::writeLog($logPath, '付款状态' . OrderStatus::getValueByName('已付款'));

        if ($orderInfo['order_status'] == OrderStatus::getValueByName('已付款')) {
            return ArrayHelper::toXml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
        }
        $transaction = DdOrder::getDb()->beginTransaction();

        try {
            FileHelper::writeLog($logPath, '模块内回调1');
            // if ($orderInfo['pay_price'] * 100 != $params['total_fee']) {
            //     return false;
            // }
            // 订单状态、微信支付订单号码更新修改
            DdOrder::updateAll([
                'order_status' => OrderStatus::getValueByName('已付款'),
                'pay_status' => 1,
                'pay_time' => time(),
                'transaction_id' => $params['transaction_id']
            ], ['order_no' => $params['out_trade_no']]);
            FileHelper::writeLog($logPath, '模块内回调2');

            // 支付减库存处理
            $order_goods = DdOrderGoods::find()->where([
                'order_id' => $orderInfo['order_id'],
                'user_id' => $orderInfo['user_id'],
                'stock_up' => 0,
                'deduct_stock_type' => 20,
            ])->select(['goods_id', 'total_num', 'goods_name'])->all();
            FileHelper::writeLog($logPath, '模块内回调3');

            $DdGoods = new DdGoods();
            // 实时获取当前商品库存
            $goods_ids = array_keys(ArrayHelper::arrayKey($order_goods, 'goods_id'));
            FileHelper::writeLog($logPath, '所有商品id' . json_encode($goods_ids));
            FileHelper::writeLog($logPath, '所有商品' . json_encode($order_goods));

            // 获取所有的商品库存
            $stocks = $DdGoods->find()
                ->where(['goods_id' => $goods_ids])
                ->select(['stock', 'goods_id'])
                ->indexBy('goods_id')
                ->asArray()
                ->all();
            FileHelper::writeLog($logPath, '所有商品库存' . json_encode($stocks));
            if (!empty($order_goods)) {
                foreach ($order_goods as $item) {
                    // 更新库存
                    // 实时库存
                    $stock = $stocks[$item['goods_id']]['stock'];
                    FileHelper::writeLog($logPath, '实时' . $stock);
                    if ($item['total_num'] > $stock) {
                        FileHelper::writeLog($logPath, $item['goods_name'] . '库存不足');
                        throw new \Exception($item['goods_name'] . '库存不足');
                    }
                    $res = DdGoods::updateAllCounters(['stock' => -$item['total_num']], ['goods_id' => $item['goods_id']]);
                    FileHelper::writeLog($logPath, '下单商品库存处理结果' . json_encode($res));
                    FileHelper::writeLog($logPath, '更新数据' . json_encode([['stock' => -$item['total_num']], ['goods_id' => $item['goods_id']]]));
                }
            }

            FileHelper::writeLog($logPath, '库存处理完成');

            // 日志状态、微信支付订单号码更新修改
            DdCorePaylog::updateAll([
                'status' => 1,
                'tid' => $params['transaction_id']
            ], ['uniontid' => $params['out_trade_no']]);


            // 返回成功  
            FileHelper::writeLog($logPath, '支付回调方法进入' . Json::encode($params));

            $transaction->commit();
        } catch (\Exception $e) {
            $transaction->rollBack();
            FileHelper::writeLog($logPath, '错误信息1' . Json::encode($e));
            throw $e;
        } catch (\Throwable $e) {
            $transaction->rollBack();
            FileHelper::writeLog($logPath, '错误信息2' . Json::encode($e));
            throw $e;
        }

        return ArrayHelper::toXml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
    }
}
